/*
	Simple Software Renderer (SSRenderer)
	Copyright (C) 2007 Piotr Orzechowski <piotr.orzechowski@gmail.com>

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#ifndef _ERRORSTACK_H
#define _ERRORSTACK_H

#include <iostream>
#include <stack>
#include <vector>

namespace util
{

namespace tmp = std;

/**
	Error stack is responsible of storing and logging error messages.
*/
class ErrorStack
{
public:

	ErrorStack() : m_pErrorStrings(NULL), m_StringsCount(0)
	{
	}

	virtual ~ErrorStack()
	{
		_Deinitialize();
	}

	/**
		Adds an output stream to which all error messages will be logged.

		@param stream custom output stream
	*/
	void AddOutputStream(tmp::ostream &stream);

	/**
		Sets a pointer to an array containing string representations
		of error codes.

		@param pErrorStrings array of NULL-ended strings describing errror codes
		@param count number of strings in the pErrorStrings array
	*/
	void SetErrorStrings(const char* pErrorStrings[], int count);

	/**
		Returns string representation of error code.

		@return string representation of error code
	*/
	const char* ErrorToString(int errorId) const;

	/**
		Pops an error code from top of the stack.

		@param pInfo reference to a pointer where additional error information will be stored

		@return error code on top of the stack, -1 if stack is empty
	*/
	int Pop(const char* &pInfo);

	/**
		Pushes an error code on top of the stack.

		@param pInfo can contain additional information on the error (such as a place where the error occured)
		@param errorCode code of the error (non-negative integer)
	*/
	void Push(const char* pInfo, int errorCode);

	/**
		Checks if stack is empty.

		@return true if stack if stack is empty, false otherwise.
	*/
	bool IsEmpty() const;

protected:

	/**
		Deinitializes the error stack.
	*/
	void _Deinitialize();

	/**
		Iterates through all output streams and dumps the top message
		from the error stack.
	*/
	void _FlushStreams();

	tmp::stack<int> m_ErrorStack;
	tmp::stack<const char*> m_InfoStack;
	tmp::vector<tmp::ostream*> m_OutputStreams;

	const char* *m_pErrorStrings;
	int	m_StringsCount;
};

} // namespace

#endif
